﻿using System;
using System.Collections.Generic;
using System.Linq;
using FluentNHibernate.Automapping;
using FluentNHibernate.Automapping.Alterations;
using Framework.Repository.Conventions;
using Framework.Repository.Testing;
using Xunit;

namespace Framework.Tests.Repository
{
    [Entity]
    public class CdtyFutureHft
    {
        protected CdtyFutureHft()
        {
        }

        public CdtyFutureHft(string name, BackOfficeFeed backOfficeFeed)
        {
            Name = name;
            BackOfficeFeed = backOfficeFeed;
        }

        public virtual int Id { get; protected set; }
        public virtual string Name { get; set; }
        public virtual BackOfficeFeed BackOfficeFeed { get; protected set; }
    }

    [Entity]
    public class BackOfficeFeed
    {
        protected BackOfficeFeed()
        {
        }

        public BackOfficeFeed(string name)
        {
            Name = name;
            CdtyFutureHfts = new List<CdtyFutureHft>();
        }

        public virtual int Id { get; protected set; }
        public virtual string Name { get; set; }
        public virtual IList<CdtyFutureHft> CdtyFutureHfts { get; protected set; }
    }

    public class CdtyFutureHftMap : IAutoMappingOverride<CdtyFutureHft>
    {
        public void Override(AutoMapping<CdtyFutureHft> mapping)
        {
            mapping.References(x => x.BackOfficeFeed);
        }
    }

    public class BackOfficeFeedMap : IAutoMappingOverride<BackOfficeFeed>
    {
        public void Override(AutoMapping<BackOfficeFeed> mapping)
        {
            mapping.HasMany(x => x.CdtyFutureHfts);
        }
    }

    public class TestOneToManyReference : IDisposable
    {
        private readonly IntegrationTest integrationTest = new IntegrationTest(
            new AutoMappingTypeProvider()
            .AddEntity<BackOfficeFeed>()
            .AddEntity<CdtyFutureHft>());

        [Fact]
        public void Should_test_reference_one_to_many()
        {
            var boRepo = integrationTest.CreateRepository<BackOfficeFeed>();
            var backOfficeFeed = new BackOfficeFeed("bo");

            Console.WriteLine("First save of BackOfficeFeed wihtout CdtyFuture");
            boRepo.Save(backOfficeFeed);

            var cdtyFutureHft = new CdtyFutureHft("future", backOfficeFeed);

            backOfficeFeed.CdtyFutureHfts.Add(cdtyFutureHft);

            Console.WriteLine("Save BackOfficeFeed with CdtyFuture");
            boRepo.Save(backOfficeFeed);

            var actual = boRepo.Where(x => x.Name == "bo").First();
            Assert.NotNull(actual);
            Assert.Equal("bo", actual.Name);
            Assert.Equal(1, actual.CdtyFutureHfts.Count);
            Assert.Equal("future", actual.CdtyFutureHfts.First().Name);

            backOfficeFeed.Name = "tutu";

            Console.WriteLine("Update BackOfficeFeed with name");
            boRepo.Save(backOfficeFeed);

            backOfficeFeed.CdtyFutureHfts.First().Name = "test";
            Console.WriteLine("Update First CdtyFuture on Name");
            boRepo.Save(backOfficeFeed);

            backOfficeFeed.CdtyFutureHfts.Clear();
            Console.WriteLine("Update BackOffice Feed with empty CdtyFuture");
            boRepo.Save(backOfficeFeed);
        }

        public void Dispose()
        {
            integrationTest.Dispose();
        }
    }
}